//
// Created by hamlet on 23-4-18.
//

#ifndef COMPILERS_GRAM_H
#define COMPILERS_GRAM_H

#include <istream>
#include <exception>
#include <stack>
#include <unordered_map>
#include <vector>
#include "Lex.h"
#include "Token.h"

// 语法分析器
class Gram {
public:
    bool analyze(std::istream &in, Lex &lex);

    std::shared_ptr<Token> root;

    static void printSyntaxTree(const std::weak_ptr<Token> &node);

    static const std::string &getTokenName(TokenType t);

private:
    static const std::vector<std::vector<TokenType>> pdList;
    static const std::unordered_map<TokenType, std::unordered_map<TokenType, int>> preTable;
    static const std::unordered_map<TokenType, std::string> tokenName;

    static void deduction(std::stack<std::shared_ptr<Token>> &st, TokenType t, int index);

    static void printType(TokenType t);

public:
    class ExcGram : public std::exception {
    };

    class ExcUnmatchedTerm : public ExcGram {
        std::string desc_;

        [[nodiscard]] const char *what() const noexcept override;

    public:
        explicit ExcUnmatchedTerm(TokenType expected, TokenType actual);
    };
};


#endif //COMPILERS_GRAM_H
